package volleyball.view;

import javax.swing.*;

import volleyball.control.DataBaseUploader;
import volleyball.control.RepeatingPlayerException;
import volleyball.model.Game;

import java.awt.*;              
import java.awt.event.*;        

/**
 * Creates the GUI for an upload panel that allows users to enter the
 * information needed to upload data to the database.
 * 
 * The upload panel will have text fields for each players name, the database path, 
 * the database username, the database password, and the date. It also contains an 
 * Upload button that creates and calls a DataBaseUploader upon activation. 
 * @author Joshua Kulhavy-Sutherland
 *
 */
public class UploadPanel implements ActionListener {
	private JLabel actionLabel;
	
	private JTextField player1;
	private JTextField player2;
	private JTextField player3;
	private JTextField player4;
	JFormattedTextField date;
	
	private JTextField dbURL;
	private JTextField dbUser;
	private JTextField dbPW;
	
	Game statistics;
	
	private JFrame frame;
	
	/**
	 * Initializes an UploadPanel that will collect information about the 
	 * Game and database from the user. It will then add the information to 
	 * the Game object.
	 * @param game The Game to add information too
	 */
	public UploadPanel(Game game){
		statistics = game;
	}
	
	/**
	 * Creates and displays an UploadPanel
	 * @param frameName The title of teh panel
	 */
	public void openPanel(String frameName){
		createJFrame(frameName);
	}
	
	/**
	 * Creates the JFrame to wrap the rest of the GUI in.
	 * @param frameName The name for the JFrame
	 */
	private void createJFrame(String frameName){
		frame = new JFrame(frameName);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.add(createJPanel());
	    frame.pack();
	    frame.setVisible(true);
	}
	
	/**
	 * Creates a JPanel for the JFrame.
	 * @return the JPanel that has been assembled, all ready for insertion into a JFrame
	 */
	private JPanel createJPanel(){
		 JPanel panel = new JPanel();
		 panel.setLayout(new BorderLayout());
		 
		//Text fields that go in the Game
	     player1 = createTextField(20);
	     player2 = createTextField(20);
	     player3 = createTextField(20);
	     player4 = createTextField(20);
	     
	     //db text fields
	     dbURL  = createTextField(20); 
	     dbUser = createTextField(20);
	     dbPW   = createTextField(20);
	     
	        //Create a formatted text field.
	        date = new JFormattedTextField(
	                java.util.Calendar.getInstance().getTime());
	        date.setActionCommand("date");
	        date.addActionListener(this);
	        		
	        //Create some labels for the fields.
	        JLabel dbLabel = new JLabel("Database Address: ");
	        dbLabel.setLabelFor(dbURL);
	        JLabel dbUserLabel = new JLabel("Database Username: ");
	        dbUserLabel.setLabelFor(dbURL);
	        JLabel passwordFieldLabel = new JLabel("Database Password: ");
	        passwordFieldLabel.setLabelFor(dbPW);
	        JLabel ftfLabel = new JLabel("Date: ");
	        ftfLabel.setLabelFor(date);
	        JLabel player1Label = new JLabel("Player 1's Name: ");
	        player1Label.setLabelFor(player1);
	        JLabel player2Label = new JLabel("Player 2's Name: ");
	        player2Label.setLabelFor(player2);
	        JLabel player3Label = new JLabel("Player 3's Name: ");
	        player3Label.setLabelFor(player3);
	        JLabel player4Label = new JLabel("Player 4's Name: ");
	        player4Label.setLabelFor(player4);
	        //TODO add a gametype, round and location field
	 
	        //Create a label to put messages during an action event.
	        actionLabel = new JLabel("Fill in the fields and hit upload.");
	        actionLabel.setBorder(BorderFactory.createEmptyBorder(10,0,0,0));
	        
	        GridBagLayout gridbag = new GridBagLayout();
	        GridBagConstraints c = new GridBagConstraints();
	 
	        panel.setLayout(gridbag);
	 
	        JLabel[] labels = {dbLabel,dbUserLabel, passwordFieldLabel, ftfLabel, player1Label, player2Label, player3Label,player4Label};
	        JTextField[] textFields = {dbURL, dbUser, dbPW, date, player1, player2, player3, player4};
	        addLabelTextRows(labels, textFields, gridbag, panel);
	 
	        c.gridwidth = GridBagConstraints.REMAINDER; //last
	        c.anchor = GridBagConstraints.WEST;
	        c.weightx = 1.0;
	        panel.add(actionLabel, c);
	        panel.setBorder(
	                BorderFactory.createCompoundBorder(
	                                BorderFactory.createTitledBorder("Text Fields"),
	                                BorderFactory.createEmptyBorder(5,5,5,5)));
	        JButton button = new JButton("Upload");
	        button.setActionCommand("Upload");
	        button.addActionListener(this);
	        button.setToolTipText("Uploads statistics to the database");
	        panel.add(button);
	        
	     return panel;
	}
	
	/**
	 * Creates and returns a JTextField with an ActionListener.
	 * @param characterLength The max length for the JTextField
	 * @return JTextField upon creation
	 */
	private JTextField createTextField(int characterLength){
		JTextField textField = new JTextField(characterLength);
		textField.addActionListener(this);
		return textField;
	}
		
	/**
	 * Add labels to the upload panel 
	 * @param labels All the JLabels that need to be added to textFields
	 * @param textFields All the JTextFields that need to have labels added, needs to be the 
	 *        same size as the JLabel array
	 * @param gridbag The gridbag layout
	 * @param container A container to put it all in (JPanel, JFrame etc.)
	 */
	private void addLabelTextRows(JLabel[] labels,
            JTextField[] textFields,
            GridBagLayout gridbag,
            Container container) {
		 GridBagConstraints c = new GridBagConstraints();
		 c.anchor = GridBagConstraints.EAST;
		 int numLabels = labels.length;

		 for (int i = 0; i < numLabels; i++) {
			 c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
			 c.fill = GridBagConstraints.NONE;      //reset to default
			 c.weightx = 0.0;                       //reset to default
			 container.add(labels[i], c);

			 c.gridwidth = GridBagConstraints.REMAINDER;     //end row
			 c.fill = GridBagConstraints.HORIZONTAL;
			 c.weightx = 1.0;
			 container.add(textFields[i], c);
		 }
	 }	
	
	/**
	 * Detects when the upload button is clicked this will place all the information
	 * the upload panel collected into the Game and then create a 
	 * DataBaseUploader and upload it to the database. 
	 * 
	 * TODO place this information in another class so that View and Control are separated
	 */
	@Override
	public void actionPerformed(ActionEvent a) {
		if (a.getActionCommand().equals("Upload")){
			if (player1.getText().equals("")||player2.getText().equals("")||
					player3.getText().equals("")||player4.getText().equals("")){
				actionLabel.setText("Please give every player a name.");
			} else if (!player1.getText().equals(player2.getText())&&!player1.getText().equals(player3.getText())&&
					!player1.getText().equals(player4.getText())&&!player2.getText().equals(player3.getText())&&
					!player2.getText().equals(player4.getText())&&!player3.getText().equals(player4.getText())){
				try {
					updatePlayerNames();
					statistics.setDate(date.getText());
					DataBaseUploader dbu = new DataBaseUploader(dbURL.getText(),dbUser.getText(),dbPW.getText());
					if(!dbu.upload(statistics)){
						System.out.println("Database upload failed.");
						//TODO make this better and more useful
					}
				} catch (RepeatingPlayerException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				frame.dispose();
			} else {
				actionLabel.setText("All 4 names must be unique to upload statistics.");
			}
		}
	}
	
	/**
	 * Updates the player names in the Game object based on the names entered in the name fields.
	 * Checks to make sure the names are not already stored in Game to make sure that all names 
	 * are unique.
	 * 
	 * @throws RepeatingPlayerException If a player's name already exists in Game. Will only happen if
	 *         Game was created using something other than the default constructor, so should never
	 *         be a problem, but still wanted to be very cautious so that the Set holding the Players
	 *         in the Game will never have a repeating key.
	 */
	private void updatePlayerNames() throws RepeatingPlayerException{
		if (statistics.containsPlayer("player1")){
			if (!statistics.containsPlayer(player1.getText())){
				if(!statistics.containsPlayer(player1.getText())) 
					statistics.getPlayer("player1").setName(player1.getText());
				throw new RepeatingPlayerException(player1.getText());
			} 
		} 
		if (statistics.containsPlayer("player2")){
			if (!statistics.containsPlayer(player2.getText())){
				if(!statistics.containsPlayer(player2.getText()))
					statistics.getPlayer("player2").setName(player2.getText());
				throw new RepeatingPlayerException(player2.getText());
			} 
		} 
		if (statistics.containsPlayer("player3")){
			if (!statistics.containsPlayer(player3.getText())){
				if(!statistics.containsPlayer(player3.getText()))
					statistics.getPlayer("player3").setName(player3.getText());
				throw new RepeatingPlayerException(player3.getText());
			} 
		} 
		if (statistics.containsPlayer("player4")){
			if (!statistics.containsPlayer(player4.getText())){
				if(!statistics.containsPlayer(player4.getText()))
					statistics.getPlayer("player4").setName(player4.getText());
				throw new RepeatingPlayerException(player4.getText());
			} 
		}	
	}
		
}
